package net.asg.games.yokeltowers.screens;

import java.util.Iterator;

import net.asg.games.yokeltowers.LevelManager;
import net.asg.games.yokeltowers.YokelTowersGame;
import net.asg.games.yokeltowers.models.YokelGameBoard;
import net.asg.games.yokeltowers.view.ColumnYokelGameObject;
import net.asg.games.yokeltowers.view.ThreeColumnYokelGameObject;
import net.asg.games.yokeltowers.view.YokelGameObject;
import net.asg.games.yokeltowers.view.YokelGameObjectFactory;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;

/**
 * @author Blakbro2k
 * 
 *         The main screen for the game. This screen is where the main game is
 *         played. All sprites and game objects are drawn here. This screen
 *         extends <code>CommonScreen</code> to minimize having to write
 *         unimplemented methods.
 */
public class GameScreen extends CommonScreen {
	protected Texture backgroundImage;

	protected Texture foregroundImage;

	protected Rectangle boardBounds;

	protected ThreeColumnYokelGameObject currentColumn;

	protected YokelGameObjectFactory yokelGameObjectFactory;

	protected Array<YokelGameObject> fallingObjects;

	protected LevelManager levelManager;

	protected BitmapFont bitmapFontName;

	protected YokelGameBoard gameboard;

	private float keyCooldown = 0;
	
	private long setTime;

	public GameScreen(YokelTowersGame game) {
		this.game = game;
	}

	public void show() {
		imageProvider = game.getImageProvider();
		soundManager = game.getSoundManager();
		soundManager.setSoundOn(true);

		backgroundImage = imageProvider.getBackground();
		debugRenderer = new ShapeRenderer();

		camera = new OrthographicCamera();
		camera.setToOrtho(false, imageProvider.getScreenWidth(),
				imageProvider.getScreenHeight());

		batch = new SpriteBatch();

		yokelGameObjectFactory = new YokelGameObjectFactory(imageProvider,
				soundManager);

		fallingObjects = new Array<YokelGameObject>();
		bitmapFontName = new BitmapFont();

		levelManager = new LevelManager(true);
		gameboard = new YokelGameBoard(yokelGameObjectFactory, 1);
		boardBounds = gameboard.getGamebounds();
		currentColumn = gameboard.resetCurrentColumn(levelManager);

		Gdx.input.setInputProcessor(this);
		Gdx.input.setCatchBackKey(true);
	}


	@Override
	public void render(float delta) {
		Gdx.gl.glClearColor(1, 1, 1, 1);
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

		camera.update();
		batch.setProjectionMatrix(camera.combined);

		if (game.isDebugOn) {
			debugRenderer.setProjectionMatrix(camera.combined);
			debugRenderer.begin(ShapeType.Rectangle);
			debugRenderer.setColor(new Color(0, 1, 0, 1));
		}

		batch.begin();
		batch.draw(backgroundImage, 0, 0);

		gameboard.renderBoard(batch, delta);
		currentColumn.draw(batch, delta);

		for(YokelGameObject fallingObject: fallingObjects) {
			fallingObject.draw(batch, delta);
		}

		if (game.isDebugOn) {
			currentColumn.drawDebug(debugRenderer);
			gameboard.renderBoardDebug(debugRenderer);
			gameboard.drawClip(boardBounds, currentColumn, debugRenderer);
		}

		batch.end();

		if (game.isDebugOn) {
			debugRenderer.end();
		}

		//process key imports
		//System.out.println(gameboard);
		//System.out.println(keyCooldown);
		keyCooldown = (keyCooldown > 0 ? keyCooldown - 1 * delta : 0);

		processInput(delta);
		
		gameboard.getBrokenObjects(fallingObjects, boardBounds);
		gameboard.doClip(boardBounds, currentColumn, Keys.DOWN);

		//Move broken objects down
		Iterator<YokelGameObject> iter = fallingObjects.iterator();
		while(iter.hasNext()) {
			YokelGameObject fo = iter.next();
			
			//if(fo instanceof ColumnYokelGameObject)
			//	fo.moveDown(delta, levelManager.getDebrisSpeed());
			//else
				fo.moveDown(delta, levelManager.getDebrisSpeed());

			if(fo instanceof ColumnYokelGameObject && ((ColumnYokelGameObject) fo).column.size > 0){
				if (gameboard.detectCollision(boardBounds, ((ColumnYokelGameObject) fo).getBlock(0))){
					gameboard.setColumn(((ColumnYokelGameObject) fo).column, boardBounds);
					iter.remove();
				}
			} 

			if(fo.isBottomOfBounds(boardBounds)) { 
				iter.remove();
			}
		}

		//Set Objects if they hit bounds
		if (gameboard.detectCollision(boardBounds, currentColumn.getBlock(0))){
			levelManager.setLevelState(YokelGameObject.BlockState.SET);
			setTime = TimeUtils.millis();
		}
		
		//Move Column down
		if (levelManager.state.equals(YokelGameObject.BlockState.FALLING)){
			currentColumn.moveDown(delta, levelManager.getFallSpeed());
			currentColumn.keepInBounds(boardBounds);
		}
		
		//Move Column down
		if (levelManager.state.equals(YokelGameObject.BlockState.SETTING) && TimeUtils.millis() - setTime > .5){
			levelManager.setLevelState(YokelGameObject.BlockState.SET);
		}

		if (levelManager.state.equals(YokelGameObject.BlockState.SET)){
			gameboard.setColumn(currentColumn.column, boardBounds);
			currentColumn = gameboard.resetCurrentColumn(levelManager);
			levelManager.setLevelState(YokelGameObject.BlockState.FALLING);
			gameboard.checkMatches(boardBounds);
		}
	}

	private void processInput(float delta) {
		levelManager.setLevelState(YokelGameObject.BlockState.FALLING);
		if (Gdx.input.isKeyPressed(Keys.DOWN) && levelManager.state.equals(YokelGameObject.BlockState.FALLING)) {
			currentColumn.moveDown(delta, levelManager.getSpeedBonus());
			gameboard.doClip(boardBounds, currentColumn, Keys.DOWN);
		}
		
		if(keyCooldown <= 0){
			if (Gdx.input.isKeyPressed(Keys.RIGHT)) {
				currentColumn.moveRight(delta);
				gameboard.doClip(boardBounds, currentColumn, Keys.RIGHT);
				keyCooldown = 0.04f;
			}

			if (Gdx.input.isKeyPressed(Keys.LEFT)) {	
				currentColumn.moveLeft(delta);
				gameboard.doClip(boardBounds, currentColumn, Keys.LEFT);
				keyCooldown = 0.04f;
			}
		}
	}

	@Override
	public boolean keyUp(int keycode) {
		if (keycode == Keys.ESCAPE || keycode == Keys.BACKSPACE) {
			Gdx.app.exit();
			return true;
		}

		if (keycode == Keys.UP) {
			((ThreeColumnYokelGameObject) currentColumn).cycleDown();
			return true;
		}

		return false;
	}
}
